package gbase

import "sync"

/*
usage:
	继承使用
	type ProductPairMap struct {
		SafeMap[int64, []uint32] //key: product.id, value: []productPair.index
	}
	xx := &ProductPairMap{*NewSafeMap[int64, []uint32]()},
*/

// 通用的线程安全Map
type SafeMap[K comparable, V any] struct {
	data map[K]V
	mu   sync.RWMutex
}

// 创建新的SafeMap
func NewSafeMap[K comparable, V any]() *SafeMap[K, V] {
	return &SafeMap[K, V]{
		data: make(map[K]V),
	}
}

// 带初始容量的创建
func NewSafeMapWithCapacity[K comparable, V any](capacity int) *SafeMap[K, V] {
	return &SafeMap[K, V]{
		data: make(map[K]V, capacity),
	}
}

// 读操作
func (sm *SafeMap[K, V]) Get(key K) (V, bool) {
	sm.mu.RLock()
	defer sm.mu.RUnlock()
	val, ok := sm.data[key]
	return val, ok
}

// 写操作
func (sm *SafeMap[K, V]) Set(key K, value V) {
	sm.mu.Lock()
	defer sm.mu.Unlock()
	sm.data[key] = value
}

// 删除操作
func (sm *SafeMap[K, V]) Delete(key K) {
	sm.mu.Lock()
	defer sm.mu.Unlock()
	delete(sm.data, key)
}

// 检查是否存在
func (sm *SafeMap[K, V]) Has(key K) bool {
	sm.mu.RLock()
	defer sm.mu.RUnlock()
	_, ok := sm.data[key]
	return ok
}

// 获取长度
func (sm *SafeMap[K, V]) Len() int {
	sm.mu.RLock()
	defer sm.mu.RUnlock()
	return len(sm.data)
}

// 清空
func (sm *SafeMap[K, V]) Clear() {
	sm.mu.Lock()
	defer sm.mu.Unlock()
	sm.data = make(map[K]V)
}

// 遍历（读锁）
func (sm *SafeMap[K, V]) Range(fn func(K, V) bool) {
	sm.mu.RLock()
	defer sm.mu.RUnlock()

	for k, v := range sm.data {
		if !fn(k, v) {
			break
		}
	}
}

// 获取所有键
func (sm *SafeMap[K, V]) Keys() []K {
	sm.mu.RLock()
	defer sm.mu.RUnlock()

	keys := make([]K, 0, len(sm.data))
	for k := range sm.data {
		keys = append(keys, k)
	}
	return keys
}

// 获取所有值
func (sm *SafeMap[K, V]) Values() []V {
	sm.mu.RLock()
	defer sm.mu.RUnlock()

	values := make([]V, 0, len(sm.data))
	for _, v := range sm.data {
		values = append(values, v)
	}
	return values
}

// 批量设置
func (sm *SafeMap[K, V]) SetBatch(data map[K]V) {
	sm.mu.Lock()
	defer sm.mu.Unlock()

	for k, v := range data {
		sm.data[k] = v
	}
}

// 复制到新map
func (sm *SafeMap[K, V]) Copy() map[K]V {
	sm.mu.RLock()
	defer sm.mu.RUnlock()

	result := make(map[K]V, len(sm.data))
	for k, v := range sm.data {
		result[k] = v
	}
	return result
}
